package com.gitee.huanminabc.db_freedom.segments;

import com.gitee.huanminabc.db_freedom.base.SqlFun;
import com.gitee.huanminabc.db_freedom.wrapper.SQL;

import java.util.concurrent.atomic.AtomicReference;

/**
 * @Author huanmin
 * @Date 2024/6/18 下午6:33
 */
public class CaseWhenImplSegments<T, Children extends SqlFunImplSegments<T, Children>> extends SqlFunImplSegments<T, Children> implements CaseWhenSegments<Children, T, SqlFun<T, ?>> {


    public CaseWhenImplSegments() {
    }

    public CaseWhenImplSegments(Class<?> entityClass, SQL sql) {
        super(entityClass, sql);
    }
    //搜索格式 CASE when column=value then value [else default] end
    public Children CASE() {
        caseWhen.append(" CASE ");
        return typedThis;
    }

    //switch 格式  CASE column then value [else default] end
    public <Y> Children CASE(SqlFun<Y, ?> column) {
        getFunFieldName(column, sqlColumn -> {
            caseWhen.append(" CASE ").append(sqlColumn.getTableName()).append(".").append(sqlColumn.getColumnName());
        });
        return typedThis;
    }

    /**
     * 搜索模式使用常亮,非搜索模式使用表达式
     * 数字或者表达式 ,如果使用表达式,需要提前将需要的表注入设置好别名,这样就可以在表达式中使用别名
     * @param expression
     * @return
     */
    public Children WHEN(Object expression) {
        caseWhen.append(" WHEN ").append(expression).append(" ");
        return typedThis;
    }
    // when column=value then value
    //因为最常用的就是=,所以这里直接写死了 ,如果是字符串那么就自动加上引号
    public <Y> Children WHEN(SqlFun<Y, ?> column ,Object param) {
        //param是字符串那么就加上引号
        if(param instanceof String){
            param="'"+param+"'";
        }
        Object finalParam = param;
        getFunFieldName(column, sqlColumn -> {
            caseWhen.append(" WHEN ").append(sqlColumn.getTableName()).append(".").append(sqlColumn.getColumnName()).append("=").append(finalParam).append(" ");
        });
        return typedThis;
    }


    /**
     * THEN 后面跟随的不仅限于简单的值或常量，它可以是任何有效的 SQL 表达式，包括算术运算、函数调用、列引用等。
     * 数字或者表达式 ,如果使用表达式,需要提前将需要的表注入设置好别名,这样就可以在表达式中使用别名
     * @param expression
     * @return
     */
    public Children THEN(Object expression) {
        caseWhen.append(" THEN ").append(expression).append(" ");
        return typedThis;
    }
    public <Y> Children THEN(SqlFun<Y, ?> column){
        getFunFieldName(column, sqlColumn -> {
            caseWhen.append(" THEN ").append(sqlColumn.getTableName()).append(".").append(sqlColumn.getColumnName()).append(" ");
        });
        return typedThis;
    }


    //数字或者表达式
    public Children ELSE(Object expression) {
        caseWhen.append(" ELSE ").append(expression).append(" ");
        return typedThis;
    }

    public <Y>  Children ELSE(SqlFun<Y, ?> column) {
        getFunFieldName(column, sqlColumn -> {
            caseWhen.append(" ELSE ").append(sqlColumn.getTableName()).append(".").append(sqlColumn.getColumnName()).append(" ");
        });
        return typedThis;
    }

    public Children END(String alias) {
        caseWhen.append(" END ").append(alias);
        SQL().addSelectColumn(caseWhen.toString());
        caseWhen=new StringBuilder();//清空
        return typedThis;
    }
    //在有些时候可以不需要别名 ,比如函数内部过滤
    public Children END() {
        caseWhen.append(" END ");
        SQL().addSelectColumn(caseWhen.toString());
        caseWhen=new StringBuilder();//清空
        return typedThis;
    }

    /**
     * 因为数据库兼容原因,这里直接用case when 语句来模拟if
     * @param expression  表达式
     * @param value_if_true
     * @param value_if_false
     * @return
     */
    public Children IF(Object expression, Object value_if_true, Object value_if_false) {
        SQL().addSelectColumn(" CASE WHEN " + expression + " THEN " + value_if_true + " ELSE " + value_if_false + " END ");
        return typedThis;
    }

    public Children IF(SqlFun<Children, Children> sql, Object value_if_true, Object value_if_false){
        //复制一份,然后清空,然后应用
        Children clone = typedThis.clone();
        clone.clear();
        Children apply = sql.apply(clone);
        String string = apply.SQL().columnAll();
        //去掉前后的空格
        SQL().addSelectColumn(" CASE WHEN " + string.trim() + " THEN " + value_if_true + " ELSE " + value_if_false + " END ");
        return typedThis;
    }



    //最常用的 if col=xx then xx else xx
    public <Y> Children IF(SqlFun<Y, ?> column,Object param, SqlFun<Y, ?> value_if_true, Object value_if_false,String alias) {
        //param是字符串那么就加上引号
        if(param instanceof String){
            param="'"+param+"'";
        }

        AtomicReference<SQL.SqlColumn> sqlColumn1 = new AtomicReference<>();
        getFunFieldName(column, sqlColumn1::set);
        AtomicReference<SQL.SqlColumn> sqlColumn2 = new AtomicReference<>();
        getFunFieldName(value_if_true, sqlColumn2::set);
        SQL().addSelectColumn(" CASE WHEN " + sqlColumn1.get().getTableName() + "." + sqlColumn1.get().getColumnName() + "=" + param +
                " THEN " + sqlColumn2.get().getTableName() + "." + sqlColumn2.get().getColumnName() + " ELSE " + value_if_false + " END ",alias);

        return typedThis;
    }
    public <Y> Children IF(SqlFun<Y, ?> column,Object param, SqlFun<Y, ?> value_if_true, Object value_if_false) {
        //param是字符串那么就加上引号
        if(param instanceof String){
            param="'"+param+"'";
        }

        AtomicReference<SQL.SqlColumn> sqlColumn1 = new AtomicReference<>();
        getFunFieldName(column, sqlColumn1::set);
        AtomicReference<SQL.SqlColumn> sqlColumn2 = new AtomicReference<>();
        getFunFieldName(value_if_true, sqlColumn2::set);
        SQL().addSelectColumn(" CASE WHEN " + sqlColumn1.get().getTableName() + "." + sqlColumn1.get().getColumnName() + "=" + param +
                " THEN " + sqlColumn2.get().getTableName() + "." + sqlColumn2.get().getColumnName() + " ELSE " + value_if_false + " END ");

        return typedThis;
    }

    public <Y>  Children IF(SqlFun<Y, ?> column, Object param, SqlFun<Y, ?> value_if_true, SqlFun<Y, ?> value_if_false){
        //param是字符串那么就加上引号
        if(param instanceof String){
            param="'"+param+"'";
        }

        AtomicReference<SQL.SqlColumn> sqlColumn1 = new AtomicReference<>();
        getFunFieldName(column, sqlColumn1::set);
        AtomicReference<SQL.SqlColumn> sqlColumn2 = new AtomicReference<>();
        getFunFieldName(value_if_true, sqlColumn2::set);
        AtomicReference<SQL.SqlColumn> sqlColumn3 = new AtomicReference<>();
        getFunFieldName(value_if_false, sqlColumn3::set);
        SQL().addSelectColumn(" CASE WHEN " + sqlColumn1.get().getTableName() + "." + sqlColumn1.get().getColumnName() + "=" + param +
                " THEN " + sqlColumn2.get().getTableName() + "." + sqlColumn2.get().getColumnName() + " ELSE " + sqlColumn3.get().getTableName() + "." + sqlColumn3.get().getColumnName() + " END ");
        return typedThis;
    }

    public  <Y> Children IF(SqlFun<Y, ?> column,Object param, Object value_if_true, Object value_if_false,String alias) {
        //param是字符串那么就加上引号
        if(param instanceof String){
            param="'"+param+"'";
        }

        Object finalParam = param;
        getFunFieldName(column, sqlColumn -> {
            SQL().addSelectColumn(" CASE WHEN " + sqlColumn.getTableName() + "." + sqlColumn.getColumnName() + "=" + finalParam + " THEN " + value_if_true + " ELSE " + value_if_false + " END ",alias);
        });
        return typedThis;

    }

    public  <Y> Children IF(SqlFun<Y, ?> column,Object param, Object value_if_true, Object value_if_false) {
        //param是字符串那么就加上引号
        if(param instanceof String){
            param="'"+param+"'";
        }

        Object finalParam = param;
        getFunFieldName(column, sqlColumn -> {
            SQL().addSelectColumn(" CASE WHEN " + sqlColumn.getTableName() + "." + sqlColumn.getColumnName() + "=" + finalParam + " THEN " + value_if_true + " ELSE " + value_if_false + " END ");
        });
        return typedThis;

    }

}
